package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.tls.TlsRSAKeyExchange;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.sound.midi.Track;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private VodService vodService;

	@Autowired
	private UserInfoFeignClient userInfoFeignClient;

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Autowired
	private TrackStatMapper trackStatMapper;

	@Override
	public UploadTrackVo uploadTrack(MultipartFile file) {
		return vodService.uploadTrack(file);
	}

	@Override
	public void saveTrackInfo(TrackInfoVo trackInfoVo) {
		//获取当前登陆用户的Id
		Long userId = AuthContextHolder.getUserId();

		//1.保存声音的基本数据
		TrackInfo trackInfo = new TrackInfo();
		trackInfo.setUserId(userId);
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		trackInfo.setSource(SystemConstant.TRACK_SOURCE_UPLOAD);
		trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);


		LambdaQueryWrapper<TrackInfo> trackInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
		trackInfoLambdaQueryWrapper.eq(TrackInfo::getAlbumId,trackInfoVo.getAlbumId());
		trackInfoLambdaQueryWrapper.orderByDesc(TrackInfo::getOrderNum);
		trackInfoLambdaQueryWrapper.last("limit  1");
		TrackInfo dbTrackInfo = trackInfoMapper.selectOne(trackInfoLambdaQueryWrapper);

		if(dbTrackInfo==null){
			trackInfo.setOrderNum(1);
		}else{
			trackInfo.setOrderNum(dbTrackInfo.getOrderNum()+1);
		}

		//媒体文件数据
		// 根据媒体文件的id从腾讯云点播服务中获取这些数据
		TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId()) ;
		trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
		trackInfo.setMediaFileId(trackInfoVo.getMediaFileId());
		trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
		trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		trackInfo.setMediaType(trackMediaInfoVo.getType());

		//上传声音数据
		trackInfoMapper.insert(trackInfo);

		//2.初始化声音的统计数据
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

		//3.修改album_info中的数据
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		Integer count  = albumInfo.getIncludeTrackCount();
		albumInfo.setIncludeTrackCount(count+1);
		albumInfoMapper.updateById(albumInfo);

	}

	@Override
	public IPage<TrackListVo> findUserTrackPage(Integer pageNum, Integer pageSize, TrackInfoQuery trackInfoQuery) {
		//获取当前登陆用户的Id
		Long userId = AuthContextHolder.getUserId();
		trackInfoQuery.setUserId(userId);

		//创建Page对象,封装分页的参数
		Page<TrackInfoVo> page  = new Page<>(pageNum , pageSize);

		//调用mapper接口完成分页查询
		IPage<TrackListVo> iPage = trackInfoMapper.findUserTrackPage(page,trackInfoQuery);


		return iPage;
	}

	@Override
	public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
		//根据声音Id查询声音数据
		TrackInfo trackInfo = new TrackInfo();
		String mediaFileId = trackInfoVo.getMediaFileId();
		String dbMediaFileId = trackInfo.getMediaFileId();
		BeanUtils.copyProperties(trackInfoVo , trackInfo);
		//声音媒体的唯一标识
		if(!mediaFileId.equals(dbMediaFileId)){
			//重新进行赋值
			TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(mediaFileId);
			trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			trackInfo.setMediaType(trackMediaInfoVo.getType());
			trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
		}
		trackInfoMapper.updateById(trackInfo);
	}

	@Override
	public void removeTrackInfo(Long id) {
		//0.根据声音的id查询声音数据
		TrackInfo trackInfo = trackInfoMapper.selectById(id);
		//1.根据声音的id删除声音的基本数据
		trackInfoMapper.deleteById(id);

		//2.根据声音的id删除声音的统计数据
		LambdaQueryWrapper<TrackStat> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(TrackStat::getTrackId,id);
		trackStatMapper.delete(lambdaQueryWrapper);

		//3.修改album_info表中的数据
		Long albumId = trackInfo.getAlbumId();
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		Integer count = albumInfo.getIncludeTrackCount();
		albumInfo.setIncludeTrackCount(count-1);
		albumInfoMapper.updateById(albumInfo);

		//4.删除云点播服务器中的媒体数据
		vodService.deleteMediaInfo(trackInfo.getMediaFileId());




	}

	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Integer pageNo, Integer pageSize) {

		// 创建一个Page对象，封装分页参数
		Page<AlbumTrackListVo> page = new Page<>(pageNo , pageSize) ;
		trackInfoMapper.findAlbumTrackPage(page , albumId) ;			// 进行条件分页查询

		// 如何构建声音列表数据中的isShowPaidMark字段的值？
		List<AlbumTrackListVo> records = page.getRecords();		// 获取当前页数据

		// 根据专辑的id查询专辑
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);

		// 判断用户是否登录了
		Long userId = AuthContextHolder.getUserId();
		if(userId == null) {		// 未登录

			// 判断专辑的付款项目的类型是否为非免费
			String payType = albumInfo.getPayType();
			if(!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(payType)) {
				//过滤掉免费的集数,剩下的展示账号
				records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() >  albumInfo.getTracksForFree())
						.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
			}

		}else  {		// 已登录

			// 获取专辑的付款类型
			String payType = albumInfo.getPayType();
			if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType)) {   // vip免费

				// 根据当前登录用户id查询用户数据
				Result<UserInfo> userInfoResult = userInfoFeignClient.findUserInfoById(userId);
				UserInfo userInfo = userInfoResult.getData();
				if(userInfo.getIsVip() == 0) {		// 非vip用户
					records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() >  albumInfo.getTracksForFree())
							.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
				}else {   // 是vip用户，判断vip是否过期了

					Date vipExpireTime = userInfo.getVipExpireTime();		// vip的过期时间

					// 当前的系统时间大于vip的过期时间，说明vip过期了
					if(new Date().after(vipExpireTime)) {
						records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() >  albumInfo.getTracksForFree())
								.forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
					}

				}

			}else if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)){		// 付费专辑
				//除了试听之外的声音
				// 判断用户是否购买过当前的声音，需要排除试听的声音。如果购买过，需要isShowPaidMark=false , 如果没有购买过isShowPaidMark=true
				List<Long> trackIds = records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.map(albumTrackListVo -> albumTrackListVo.getTrackId()).collect(Collectors.toList());

				// 判断用户是否购买过这些声音
				/**
				 * 后期如果用户购买了专辑或者某些声音，此时会在ting_user数据库中的user_paid_album、user_paid_track表中记录购买信息
				 * user_paid_album表中记录的是专辑购买的信息
				 * user_paid_track表中记录的是声音购买的信息
				 */
				//trackIds是需要除了试听外的声音,这个接口是查询这个声音有没有被购买
				Result<Map<Long, Integer>> isPaidTrackResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIds);
				Map<Long, Integer> resultData = isPaidTrackResult.getData();

				// 构建records中的每一个声音的isShowPaidMark字段的值
				records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
						.forEach(albumTrackListVo -> {
							//key
							Long trackId = albumTrackListVo.getTrackId();
							//value
							Integer isPaid = resultData.get(trackId);
							//给isShow
							boolean isShowPaidMark = isPaid == 0 ;
							albumTrackListVo.setIsShowPaidMark(isShowPaidMark);
						});

			}

		}
		return  page;
	}

	@Override
	public void trackStatUpdate(TrackStatMqVo trackStatMqVo) {

		String type = trackStatMqVo.getStatType();
		if(SystemConstant.ALBUM_STAT_PLAY.equals(type)){
			//更新声音的播放量
			Long trackId = trackStatMqVo.getTrackId();
			LambdaQueryWrapper<TrackStat> lambdaQueryWrapper = new LambdaQueryWrapper<TrackStat>();
			lambdaQueryWrapper.eq(TrackStat::getTrackId,trackId);
			lambdaQueryWrapper.eq(TrackStat::getStatType,SystemConstant.TRACK_STAT_PLAY);
			TrackStat trackStat = trackStatMapper.selectOne(lambdaQueryWrapper);
			trackStat.setStatNum(trackStat.getStatNum()+trackStatMqVo.getCount());
			trackStatMapper.updateById(trackStat);

			//更改专辑的播放量
			Long albumId = trackStatMqVo.getAlbumId();
			LambdaQueryWrapper<AlbumStat> albumStatLambdaQueryWrapper = new LambdaQueryWrapper<AlbumStat>();
			albumStatLambdaQueryWrapper.eq(AlbumStat::getAlbumId,albumId);
			albumStatLambdaQueryWrapper.eq(AlbumStat::getStatType,SystemConstant.ALBUM_STAT_PLAY);
			AlbumStat albumStat = albumStatMapper.selectOne(albumStatLambdaQueryWrapper);
			albumStat.setStatNum(albumStat.getStatNum()+trackStatMqVo.getCount());
			albumStatMapper.updateById(albumStat);



		}
	}

	@Override
	public TrackStatVo getTrackStatVo(Long trackId) {
		TrackStatVo trackStatVo = trackStatMapper.getTrackStatVo(trackId) ;
		return trackStatVo;
	}

	//查询声音购买的分集列表
	@Override
	public List<TrackPayVo> findUserTrackPaidList(Long trackId) {        // 查询大于当前声音orderNum的id的声音

		// 根据声音的id查询声音数据
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

		// 从声音数据中获取到专辑的id
		Long albumId = trackInfo.getAlbumId();
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);

		// 查询当前登录用户购买的声音列表 从声音数据中获取专辑id 根据专辑id查询当前用户登录的声音列表
		Result<List<Long>> userPaidTrackListResult = userInfoFeignClient.findUserPaidTrackList(albumId);
		List<Long> userPaidTrackList = userPaidTrackListResult.getData(); //userPaidTrackList就是当前用户购买的声音id

		// 查询当前专辑声音的orderNum大于当前用户点击的声音的声音列表
		LambdaQueryWrapper<TrackInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(TrackInfo::getAlbumId, albumId);
		lambdaQueryWrapper.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
		lambdaQueryWrapper.orderByAsc(TrackInfo::getOrderNum);
		lambdaQueryWrapper.select(TrackInfo::getId);   // 指定查询列
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(lambdaQueryWrapper);
		List<Long> trackInfoIds = trackInfoList.stream().map(track -> track.getId()).collect(Collectors.toList());

		// 从第四步到的的声音集合中排除购买过的声音，得到未购买过的声音的列表
		List<Long> ids = new ArrayList<>();  // 作用：存储未购买过的声音id
		if (CollectionUtils.isEmpty(userPaidTrackList)) {        // 不存在购买过的声音
			ids = trackInfoIds;
		} else {  // 存在购买过的声音
			ids = trackInfoIds.stream().filter(id -> !userPaidTrackList.contains(id)).collect(Collectors.toList());
		}

		// 第五步得到的声音列表为准构建声音购买分集列表
		List<TrackPayVo> trackPayVoList = new ArrayList<>();

		// 本集
		TrackPayVo trackPayVo = new TrackPayVo();
		trackPayVo.setName("本集");
		trackPayVo.setPrice(albumInfo.getPrice());
		trackPayVo.setTrackCount(0);
		trackPayVoList.add(trackPayVo);

		// 以10集为一个单位构建分集列表
		int count = ids.size();
		if (count > 0 && count <= 10) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后" + count + "集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		if (count > 10) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后10集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(10)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(10);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		// 大于10
		if (count > 10 && count <= 20) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后" + count + "集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		// 大于20
		if (count > 20) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后20集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(20)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(20);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		if (count > 20 && count <= 30) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后" + count + "集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		// 大于30
		if (count > 30) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后30集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(40)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(30);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		if (count > 30 && count <= 50) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后" + count + "集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(count);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		// 大于50
		if (count > 50) {
			TrackPayVo trackPayVoAfterCount = new TrackPayVo();
			trackPayVoAfterCount.setName("后50集");
			BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50)).multiply(new BigDecimal("10"))
					.divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
			trackPayVoAfterCount.setPrice(price);
			trackPayVoAfterCount.setTrackCount(50);
			trackPayVoList.add(trackPayVoAfterCount);
		}

		return trackPayVoList;
	}


	@Override
	public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {

		// 创建一个List集合对象，用来存储查询的结果数据
		List<TrackInfo> trackInfoList = new ArrayList<>() ;

		// 根据声音的id查询声音数据
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

		// 获取专辑的id
		Long albumId = trackInfo.getAlbumId();

		// 从track_info表中查询需要购买的声音列表(需要排除已经购买过的声音id)
		// select * from track_info where album_id = ? and order_num > ? and id not in(....) limit ?
		Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(albumId);
		List<Long> userPaidTrackIds = userPaidTrackList.getData();

		// 判断trackCount是否大于0
		if(trackCount > 0) {

			LambdaQueryWrapper<TrackInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>() ;
			lambdaQueryWrapper.eq(TrackInfo::getAlbumId, albumId) ;
			lambdaQueryWrapper.gt(TrackInfo::getOrderNum , trackInfo.getOrderNum()) ;
			lambdaQueryWrapper.orderByAsc(TrackInfo::getOrderNum) ;
			if(!CollectionUtils.isEmpty(userPaidTrackIds)) {
				lambdaQueryWrapper.notIn(TrackInfo::getId, userPaidTrackIds) ;
			}
			lambdaQueryWrapper.last("limit " + trackCount) ;
			trackInfoList = trackInfoMapper.selectList(lambdaQueryWrapper);

		}else {		// 购买的是本集
			trackInfoList.add(trackInfo) ;
		}

		return trackInfoList;
	}


	private  void  saveTrackStat(Long trackId,String statType){
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		trackStat.setStatNum(0);

		trackStatMapper.insert(trackStat);

	}


}
